package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.zzyl.dto.LoginDto;
import com.zzyl.entity.Resource;
import com.zzyl.entity.User;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.mapper.RoleResourceMapper;
import com.zzyl.mapper.UserMapper;
import com.zzyl.mapper.UserRoleMapper;
import com.zzyl.properties.JwtTokenProperties;
import com.zzyl.service.LoginService;
import com.zzyl.utils.JwtUtil;

import com.zzyl.vo.LoginVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private JwtTokenProperties jwtTokenProperties;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleResourceMapper roleResourceMapper;
    @Autowired
    private ResourceMapper resourceMapper;

    @Override

    public LoginVo login(LoginDto dto) {

        User user = userMapper.selectByUsername(dto.getUsername());
        if(ObjectUtil.isEmpty(user)){
            throw new BaseException(BasicEnum.INCORRECT_PASSWORD);
        }
        //todo 2，判断redis是否有用户的密码错误次数
        String redisKey = "user:password:error:count:" + user.getId();
        String redisData = stringRedisTemplate.opsForValue().get(redisKey);
        redisData = StrUtil.nullToDefault(redisData,"0");
        int count =Integer.parseInt(redisData);
        //次数大于3，则表示用户已被冻结
        if(count >= 3){
            throw new RuntimeException("密码错误次数已达上限，账号已被冻结，请稍后再试！");
        }
        if(!DigestUtil.bcryptCheck(dto.getPassword(),user.getPassword())){
            //todo 记录错误次数，将数据存到redis(userId，+1，过期时间)
            stringRedisTemplate.opsForValue().set(redisKey,String.valueOf(++count),6,TimeUnit.HOURS);
            throw new BaseException(BasicEnum.INCORRECT_PASSWORD);
        }
        stringRedisTemplate.delete(redisKey);

        //拿到角色Id集合
        List<Long> list =  userRoleMapper.selectByUserId(user.getId());
//        遍历集合拿到资源集合
        Set<String> set = new HashSet<>();
        for (Long roleId : list) {
            Set<String> s = roleResourceMapper.selectResourceNoByRoleId(roleId);
            set.addAll(s);
        }
        List<String> list1 = new ArrayList<>();
        for (String s : set) {
           Resource resource = resourceMapper.selectByResourceNo(s);
           list1.add(resource.getRequestPath());
        }
        String s= JSONUtil.toJsonStr(list1);
        String key = "path:request";

        stringRedisTemplate.opsForValue().set(key+user.getId().toString(),s);

        //生成jwt令牌
        Map<String, Object> map = new HashMap<>();
        map.put("id",user.id);
        String jwt = JwtUtil.createJWT(jwtTokenProperties.getSecretKey(), jwtTokenProperties.getTtl(), map);

        LoginVo loginVo = BeanUtil.toBean(user, LoginVo.class);
        loginVo.setUserToken(jwt);
        return loginVo;

    }
}
